package com.blyat.xsoft.kernel.component.extension;

import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @Auther: syh
 * @Date: 2020/9/28
 * @Description:
 */
public class ExtensionClass<T> {

    private Class<? extends T> clazz;

    public ExtensionClass(Class<? extends T> clazz) {
        this.clazz = clazz;
    }

    public T getExtInstance() {
        if (clazz == null) {
            throw new RuntimeException("Class of ExtensionClass is null");
        }
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("create " + clazz.getCanonicalName() + " instance error", e);
        }
    }

    public T getExtInstance(ApplicationContext context) {
        if (clazz == null) {
            throw new RuntimeException("Class of ExtensionClass is null");
        }
        if (context == null) {
            return getExtInstance();
        }
        try {
            return (T) context.getAutowireCapableBeanFactory()
                    .createBean(clazz, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
        } catch (Exception e) {
            throw new RuntimeException("create " + clazz.getCanonicalName() + " instance error", e);
        }
    }

    public T getExtInstance(Class[] argTypes, Object[] args) {
        if (clazz == null) {
            throw new RuntimeException("Class of ExtensionClass is null");
        }
        try {
            Constructor<? extends T> constructor = clazz.getDeclaredConstructor(argTypes);
            return constructor.newInstance(args);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("create " + clazz.getCanonicalName() + " instance error", e);
        }
    }
}
